<?php
/**
 * Description:
 *
 * @author      Eden
 * @datetime    2016/12/28 00:40
 * @copyright   Beijing CmsTop Technology Co.,Ltd.
 */

class Order_Model extends WX_Model
{

    private $orderError = '';

    const PAGE_SIZE = 20;

    private $formatStatus = array(
        'Unpaid' => '等待付款',
        'Pending' => '等待发货',
        'Dispatch' => '已发货',
        'Complete' => '已完成',
        'Refund' => '退款中',
        'Refunded' => '已退款',
        'Cancel' => '已取消'
    );

    /**
     * 初始化
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 订单列表
     * @param $userid
     * @param string $type
     * @param int $page
     * @return array
     */
    public function getOrderLists($userid, $type = '', $page = 1)
    {

        $page = empty($page) ? 1 : $page;
        $offset = ($page - 1) * self::PAGE_SIZE;

        $where = array();
        $where['userId'] = $userid;
        if (!empty($type)) {
            $where['status'] = $type;
        }
        if ($type == 'Complete') {
            $where['commented'] = 0;
        }

        $countDb = clone($this->db);
        $countDb->where($where);
        $counts = $countDb->count_all_results('user_order');
        if ($counts == 0) {
            return array(
                'total' => 0,
                'nextPage' => false,
                'data' => array()
            );
        }

        $query = $this->db->select()
            ->from('user_order')
            ->limit(self::PAGE_SIZE, $offset)
            ->where($where)
            ->order_by('created', 'DESC')
            ->get();

        $orders = $query->result_array();

        return array(
            'total' => $counts,
            'nextPage' => $counts > ($page * self::PAGE_SIZE),
            'data' => $this->_searchGoods($orders)
        );
    }

    private function _searchGoods($orders)
    {
        $orderIds = array();
        if (!empty($orders) && is_array($orders)) foreach ($orders as $order) {
            array_push($orderIds, $order['id']);
        }

        $goodsDb = clone($this->db);
        $query = $goodsDb->select('uog.num, uog.orderId, uog.goodsId, sg.goodsName,
            sg.baseId, sg.thumb, sg.liveUrl, sg.expressWeight, sg.status, r.id as ruleId, r.salePrice as price, r.name as ruleName')
            ->where_in('uog.orderId', $orderIds)
            ->from('user_order_goods as uog')
            ->join('base_goods_rule as r', 'r.id=uog.ruleId')
            ->join('base_goods as sg', 'sg.id = uog.goodsId')
            ->get();
        $results = $query->result_array();
        $ordersGoods = array();
        if ($results) foreach ($results as $item) {
            $orderId = $item['orderId'];
            if (empty($ordersGoods[$orderId])) {
                $ordersGoods[$orderId] = array();
            }

            $goodsItem = array(
                'goodsId' => (int) value($item, 'goodsId'),
                'goodsName' => value($item, 'goodsName'),
                'num' => (int) value($item, 'num'),
                'price' => intval($item['price']),
                'price_format' => money_format('%i', $item['price'] / 100),
                'baseId' => intval($item['baseId']),
                'thumb' => thumb($item['thumb'], 200, 200),
                'expressWeight' => doubleval($item['expressWeight']),
                'status' => $item['status'] == 1 ? 'onSale' : 'offSale',
                'isLive' => !empty($item['liveUrl']),
                'liveUrl' => value($item, 'liveUrl', ''),
                'ruleId' => $item['ruleId'],
                'ruleName' => $item['ruleName']
            );
            $ordersGoods[$orderId][] = $goodsItem;
        }

        $ret = array();
        foreach($orders as $goods) {
            $orderId = $goods['id'];
            if (empty($ordersGoods[$orderId])) {
                continue;
            }
            $returns = array();
            $returns['orderId'] = (int) $goods['id'];
            $returns['sn'] = value($goods, 'sn');
            $returns['totalPrice'] = money_format('%i', $goods['totalPrice'] / 100);
            $returns['goodsPrice'] = doubleval($goods['goodsPrice']);
            $returns['expressPrice'] = doubleval($goods['expressPrice']);
            $returns['voucher'] = $goods['voucher'];
            $returns['addressId'] = (int) value($goods, 'addressId');
            $returns['payMode'] = value($goods, 'payMode', 'online');
            $returns['created'] = value($goods, 'created');
            $returns['status'] = value($goods, 'status');
            $returns['formatStatus'] = $this->formatStatus[$goods['status']];
            $returns['message'] = value($goods, 'message', '');
            $returns['goods'] = $ordersGoods[$orderId];
            $returns['commented'] = intval($goods['commented']);
            $ret[] = $returns;
        }

        return $ret;
    }

    /**
     * 下单
     * @param $data
     * @param $goods
     * @return array|bool
     */
    public function add($data, $goods, $payStatus = 0)
    {
        $data = [
            'sn' => sn(),
            'userId' => $data['userId'],
            'totalPrice' => $data['totalPrice'],
            'goodsPrice' => $data['goodsPrice'],
            'expressPrice' => $data['expressPrice'],
            'addressId' => $data['expressId'],
            'balancePrice' => $data['balance'],
            'integralPrice' => $data['integralPrice'],
            'integral' => $data['integral'],
            'voucherPrice' => $data['voucherPrice'],
            'voucher' => $data['voucherId'],
            'message' => $data['message'],
            'created' => date('Y-m-d H:i:s'),
            'payMode' => 'online',
            'payWay' => 2,          // 2 微信支付
            'payStatus' => $data['totalPrice'] == 0 ? 6 : 0,
            'status' => $data['totalPrice'] == 0 ? 'Pending' : 'Unpaid'
        ];

        try {

            $orderDb = clone($this->db);
            $orderDb->trans_start();
            $orderDb->insert('user_order', $data);
            $orderId = $orderDb->insert_id();

            if (empty($orderId)) {
                $this->setError('下单失败');
                return false;
            }

            $goodsData = [];
            foreach($goods as $item) {
                $goodsData[] = [
                    'orderId' => $orderId,
                    'goodsId' => $item['goodsId'],
                    'ruleId' => $item['ruleId'],
                    'num' => $item['num'],
                    'price' => $item['price']
                ];
            }

            $uogDb = clone($this->db);
            $uogDb->insert_batch('user_order_goods', $goodsData);

            // 更新 car 表
            if (empty($this->updateCars($data['userId']))) {
                $this->setError('下单失败');
                return false;
            }

            $orderDb->trans_complete();
            if ($orderDb->trans_status()) {
                @statIncr('wxOrders');
                return array_merge($data, ['orderId' => $orderId]);
            }
        } catch (Exception $e) {
            $this->setError('下单失败');
        }

        return false;
    }

    public function afterPaid($orderId)
    {
        $odb = clone($this->db);
        $q = $odb->get_where('user_order', ['id' => $orderId]);
        $row = $q->row_array();

        if (empty($row)) {
            return false;
        }

        // 优惠券
        if (!empty($row['voucher'])) {
            // 标记优惠券已使用
            $userTicketDb = clone($this->db);
            $userTicketDb->where(['userid' => $row['userId'], 'ticketid' => $row['voucher']]);
            $userTicketDb->update('user_ticket', ['used' => 1, 'used_time' => dateTime()]);
        }

        // 积分
        if (!empty($row['integral'])) {

            // 从 user 表扣除积分
            $userDB = clone($this->db);
            $userDB->where('id', $row['userId']);
            $userDB->set("score", "score-{$row['integral']}", false);
            $userDB->update('user');

            // 记录到 record 表
            $integralDB = clone($this->db);
            $integralDB->insert('user_score_record', [
                'userid' => $row['userId'],
                'score' => $row['integral'],
                'type' => 'charge',
                'orderid' => $orderId,
                'amount' => $row['integralPrice'],
                'note' => '购买商品',
            ]);
        }

        // 钱包
        if (!empty($row['balancePrice'])) {
            $userdb = clone($this->db);
            $userdb->where('id', $row['userId']);
            $this->db->set('amount', "amount-" . $row['balancePrice'], FALSE);
            $this->db->update('user');

            //资源流向记录
            $cashDb = clone($this->db);
            $cashDb->insert('user_cash_record', [
                'userid' => $row['userId'],
                'type' => 'buy',
                'created' => dateTime(),
                'amount' => $row['balancePrice'],
                'note' => '商品消费'
            ]);
        }

        return true;
    }

    /**
     * 删除购物里里已经购买过的商品
     * @param int $userId
     */
    private function updateCars($userId)
    {
        $db = clone($this->db);
        $db->where(['userId' => $userId, 'selected' => 1]);
        $db->delete('user_car');
        return $db->affected_rows();
    }

    /**
     * 修改订单
     * @param $orderid
     * @param $status
     * @return bool
     */
    public function modify($orderid, $status)
    {

        try {
            $db = clone($this->db);

            $db->where(['id' => $orderid]);
            if ($status == 'Cancel') {
                $db->update('user_order', ['status' => $status]);
            } else {
                $db->delete('user_order');
            }

            return $db->affected_rows();

        } catch (Exception $e) {}
        return false;
    }

    /**
     * 商品详情
     * @return array|bool
     */
    public function getContent($orderId, $addressId = 0)
    {
        try {
            $orderDb = clone($this->db);
            $query = $orderDb->get_where('user_order', array('id' => $orderId));
            $row = $query->row_array();
            if (empty($row)) {
                $this->setError('该订单不存在');
                return false;
            }

            $goodsDb = clone($this->db);
            $query = $goodsDb->select('uog.num, uog.price, uog.orderId, uog.goodsId, sg.goodsName, sg.streamId, sg.baseId,
                sg.thumb, sg.liveUrl, sg.status, r.id as ruleId, r.name as ruleName, r.salePrice')
                ->where_in('uog.orderId', $orderId)
                ->from('user_order_goods as uog')
                ->join('base_goods_rule as r', 'r.id=uog.ruleId')
                ->join('base_goods as sg', 'sg.id = uog.goodsId')
                ->get();

            $results = $query->result_array();
            $this->load->library('core/upload', null, 'up');
            $items = array();
            if ($results && is_array($results)) foreach($results as $item) {
                $goodsItem = array(
                    'goodsId' => (int) value($item, 'goodsId'),
                    'goodsName' => value($item, 'goodsName'),
                    'num' => (int) value($item, 'num'),
                    'price' => $item['salePrice'],
                    'price_format' => money_format('%i', $item['salePrice'] / 100),
                    'thumb' => thumb($item['thumb'], 100, 100),
                    'status' => $item['status'] == 1 ? 'onSale' : 'offSale',
                    'isLive' => !empty($item['liveUrl']),
                    'liveUrl' => value($item, 'liveUrl', ''),
                    'ruleId' => $item['ruleId'],
                    'ruleName' => $item['ruleName']
                );
                $items[] = $goodsItem;
            }

            $goods = $row;
            $returns = array();
            $returns['orderId'] = (int) $goods['id'];
            $returns['sn'] = value($goods, 'sn');
            $returns['totalPrice'] = money_format('%i', $goods['totalPrice'] / 100);
            $returns['goodsPrice'] = money_format('%i', $goods['goodsPrice'] / 100);
            $returns['expressPrice'] = money_format('%i', $goods['expressPrice'] / 100);
            $returns['balancePrice'] = money_format('%i', $goods['balancePrice'] / 100);
            $returns['voucherPrice'] = money_format('%i', $goods['voucherPrice'] / 100);
            $returns['ingetralPrice'] = money_format('%i', $goods['integralPrice'] / 100);
            $returns['voucher'] = doubleval($goods['voucher']);
            $returns['payMode'] = value($goods, 'payMode', 'online');
            $returns['addressId'] = (int) value($goods, 'addressId');
            $returns['created'] = value($goods, 'created');
            $returns['distribution'] = $this->getExpress($orderId);
            $returns['status'] = value($goods, 'status');
            $returns['statusFormat'] = $this->formatStatus[$goods['status']];
            $returns['goods'] = $items;
            $returns['message'] = value($goods, 'message', '');
            $returns['address'] = $this->getAddress($goods['addressId'], $addressId, $goods['id']);
            $returns['refund'] = $this->getRefund($goods['id'], $goods['status']);
            return $returns;

        } catch (Exception $e) {
            $this->setError('订单获取失败');
        }
        return false;
    }

    /**
     * @param $id
     * @param $status
     * @return array
     */
    private function getRefund($id, $status)
    {
        if ($status != 'Refund' && $status != 'Refunded') {
            return [];
        }
        $db = clone($this->db);
        $query = $db->select('actualAmount, cause, remark, refundAmount, status')->get_where('user_order_refund', ['orderId' => $id]);
        $row = $query->row_array();
        if ($row) {
            $row['refundAmount'] = '￥' . money_format('%i', $row['refundAmount']);
        }
        return $row;
    }

    /**
     * 获取收货人信息
     * @param $addressId
     * @return array
     */
    protected function getAddress($addressId, $newAddressId = 0, $orderId = 0)
    {
        $add = array(
            'name' => '',
            'phone' => '',
            'address' => ''
        );

        if (!empty($newAddressId) && !empty($orderId)) {
            $oDb = clone($this->db);
            $oDb->where('id', $orderId);
            $oDb->update('user_order', ['addressId' => $newAddressId]);
            if ($oDb->affected_rows()) {
                $addressId = $newAddressId;
            }
        }

        if (empty($addressId)) {
            return $add;
        }
        $addDb = clone($this->db);
        $query = $addDb->get_where('user_address', array('id' => $addressId));
        $result = $query->row_array();
        if (empty($result)) {
            return $add;
        }

        $add['name'] = value($result, 'name');
        $add['phone'] = value($result, 'phone');
        $add['address'] = sprintf('%s %s %s %s', $result['province'], $result['city'], $result['area'], $result['address']);
        return $add;
    }

    /**
     * 快递
     * @param $orderId
     * @return mixed
     */
    public function getExpress($orderId)
    {
        $return['expressNo'] = '';
        $return['expressName'] = '';
        $return['expressTime'] = '';
        $query = $this->db->get_where('user_order_express', array('orderId' => $orderId));
        $row = $query->row_array();
        if ($row) {
            $return['expressNo'] = value($row, 'expressNo');
            $return['expressName'] = value($row, 'expressName');
            $return['expressTime'] = value($row, 'created');
        }
        return $return;
    }

    /**
     * 修改状态
     * @param $orderId
     * @param $status
     * @return bool
     */
    public function chgStatus($orderId, $status)
    {
        $db = clone($this->db);
        $db->where('id', $orderId);

        $data = ['status' => $status];
        if ($status == 'Complete') {
            $data['compTime'] = dateTime();
        }

        $db->update('user_order', $data);
        if ($db->affected_rows()) {
            return true;
        }
        return false;
    }

    public function getOrderError()
    {
        return $this->orderError;
    }

    /**
     * 再来一单
     * @param $orderId
     * @return bool
     */
    public function buyMore($orderId)
    {
        // 订单
        $db = clone($this->db);
        $query = $db->get_where('user_order', ['id' => $orderId]);
        $order = $query->row_array();
        unset($query, $db);
        if (empty($order)) {
            return false;
        }

        // 商品
        $db = clone($this->db);
        $query = $db->get_where('user_order_goods', ['orderId' => $orderId]);
        $goods = $query->result_array();
        unset($query, $db);
        if (empty($goods)) {
            return false;
        }

        $goodsIds = [];
        $goodsItems = [];
        $ruleIds = [];
        foreach($goods as $item) {
            $goodsIds[] = $item['goodsId'];
            $goodsItems[$item['goodsId']] = $item;

            $ruleIds[] = $item['ruleId'];
            $newItems[$item['ruleId']] = $item;
        }

        // 找到所有商品
        $goodsDB = clone($this->db);
        $goodsDB->where_in('id', $goodsIds);
        $goodsQuery = $goodsDB->get('base_goods');
        $goodsRow = $goodsQuery->result_array();
        if (empty($goodsRow)) {
            $this->orderError = '商品不存在';
            return false;
        }

        $goodsInfos = [];
        foreach ($goodsRow as $r) {
            $goodsInfos[$r['id']] = $r;
        }

        $ruleDB = clone($this->db);
        $ruleDB->where_in('id', $ruleIds);
        $ruleQuery = $ruleDB->get('base_goods_rule');
        $ruleRows = $ruleQuery->result_array();
        if (empty($ruleRows)) {
            return false;
        }

        // 判断老商品是否有下架或库存不中的商品
        $newGoods = [];
        foreach ($ruleRows as $r) {
            $ruleId = $r['id'];
            if (!array_key_exists($ruleId, $newItems)) {
                $this->orderError = '部分商品已下架';
                return false;
            }

            $item = $newItems[$ruleId];
            if ($item['num'] > $r['stock']) {
                $this->orderError = '部分商品库存不足';
                return false;
            }

            $goodsinfo = $goodsInfos[$r['goods_id']];
            $newGoods[] = [
                'goodsId' => $r['goods_id'],
                'ruleId' => $ruleId,
                'expType' => $goodsinfo['expType'],
                'expAmount' => $goodsinfo['expAmount'],
                'num' => $item['num'],
                'price' => $r['salePrice'],
                'expWeight' => $r['expressWeight']
            ];
        }

        // 新商品的价格

        $data = [];
        $data['userId'] = $order['userId'];
        $data['sn'] = sn();
        $data['addressId'] = $order['addressId'];
        $data['payMode'] = 'online';
        $data['payWay'] = 2;
        $data['created'] = dateTime();
        $data['status'] = 'Unpaid';

        $orderDb = clone($this->db);
        $orderDb->insert('user_order', $data);
        $newOrderId = $orderDb->insert_id();
        if (empty($newOrderId)) {
            return false;
        }

        // 价格要使用现在的价格
        $newOrderGoods = [];
        $update = [];
        $goodsPrice = 0;
        $totalPrice = 0;
        foreach($newGoods as $item) {
            $newOrderGoods[] = [
                'orderId' => $newOrderId,
                'goodsId' => $item['goodsId'],
                'ruleId' => $item['ruleId'],
                'num' => $item['num'],
                'price' => $item['price']
            ];

            $goodsPrice += $item['num'] * $item['price'];
        }
        $uogDb = clone($this->db);
        $uogDb->insert_batch('user_order_goods', $newOrderGoods);

        // 物流价格
        $this->load->model('common/ExpressPrice_Model', 'e');
        $price = $this->e->calc($newGoods);

        $orderDb1 = clone($this->db);
        $orderDb1->where('id', $newOrderId);
        $orderDb1->update('user_order', [
            'totalPrice' => $goodsPrice + $price,
            'expressPrice' => $price,
            'goodsPrice' => $goodsPrice
        ]);

        return $newOrderId;
    }


    /**
     * 修改一个字段
     * @param $orderId
     * @param $field
     * @param string $value
     * @return mixed
     */
    public function updateField($orderId, $field, $value = '')
    {
        $db = clone($this->db);
        $db->where('id', $orderId);

        if (is_string($field)) {
            $db->update('user_order', [$field => $value]);
        } else if(is_array($field)) {
            $db->update('user_order', $field);
        }

        return $db->affected_rows();
    }

    /**
     * 订单信息
     * @param $orderId
     * @return mixed
     */
    public function getOrder($orderId)
    {
        $db = clone($this->db);
        $query = $db->get_where('user_order', ['id' => $orderId]);
        return $query->row_array();
    }

    /**
     * @param $params
     * @param $userid
     * @return bool
     */
    public function commentsGoods($params, $userid)
    {
        $orderId = $params['orderId'];
        $expressStar = intval($params['express']);

        $db = clone($this->db);
        $db->insert('user_order_express_stars', [
            'orderId' => $orderId,
            'stars' => $expressStar
        ]);
        unset($db);

        $comments = [];
        foreach($params['goods'] as $c) {
            $comments[] = [
                'goodsId' => $c['goodsId'],
                'userId' => $userid,
                'content' => $c['message'],
                'created' => dateTime(),
                'expressStars' => $expressStar,
                'goodsStars' => $c['star'],
                'anonymous' => value($params, 'anonymous', 0),
                'status' => 1
            ];
        }

        $db = clone($this->db);
        $db->insert_batch('base_goods_comments', $comments);
        unset($db);

        $db = clone($this->db);
        $db->where('id', $orderId);
        $db->update('user_order', ['commented' => 1]);
        return true;
    }

    /**
     * 申请退款
     * @param $order
     * @param $userid
     * @param string $message
     * @return bool
     */
    public function doRefund($order, $userid, $message = '')
    {
        $orderId = $order['id'];
        $data = [
            'orderId' => $orderId,
            'userId' => $userid,
            'cause' => $message,
            'actualAmount' => $order['totalPrice'],
            'created' => dateTime()
        ];
        $db = clone($this->db);
        $db->insert('user_order_refund', $data);
        if (!$db->insert_id()) {
            return false;
        }
        unset($db);

        $db = clone($this->db);
        $db->where('id', $orderId);
        $db->update('user_order', [
            'status' => 'Refund'
        ]);
        // user_order_refund
        return $db->affected_rows();
    }
}



